package com.lime49.lockcrypt;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.JOptionPane;
import javax.swing.event.*;
import java.awt.event.InputEvent;
import java.awt.dnd.*;
import java.awt.Point;
import java.awt.Cursor;
import java.awt.datatransfer.Transferable;
import java.util.ResourceBundle;
import java.text.MessageFormat;

public class AccountTree extends JTree implements TreeSelectionListener, DragGestureListener, DropTargetListener, DragSourceListener {
        protected DefaultMutableTreeNode selectedNode = null;
        protected TreePath selectedTreePath = null;
        private DragSource dragSource = null;
        private DragSourceContext dragSourceContext = null;
        private DefaultMutableTreeNode rootNode;
        private FrmMainWindow parent;
        private ResourceBundle lang;
        
        public AccountTree(DefaultMutableTreeNode root, FrmMainWindow parent) {
            super(root);
            this.parent = parent;
            this.lang = parent.getLanguage();
            rootNode = root;
            addTreeSelectionListener(this);
            dragSource = DragSource.getDefaultDragSource();
            DragGestureRecognizer dragGest = dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this);
                                                                                         //dragSource,                  DragGestureListener
            dragGest.setSourceActions(dragGest.getSourceActions() &~InputEvent.BUTTON3_MASK); // ignores right clicks which could screw with the popupmenu
            DropTarget dropTarget = new DropTarget(this, this); //Component to associate target with, DragTargetListener
            
        }
        
        public DefaultMutableTreeNode getRootNode() {
            return rootNode;
        }
        /**
         * Returns the selected Tree Node
         * @return The selected Tree Node
         */
        public DefaultMutableTreeNode getSelectedNode() {
            return selectedNode;
        }
        public void dragGestureRecognized(DragGestureEvent e) {
            if(selectedNode != null) {
                Transferable transferable = (Transferable)selectedNode;
                Cursor cursor = DragSource.DefaultMoveDrop;
                try {
                    dragSource.startDrag(e, cursor, transferable, this);
                } catch(Exception ignore) {/* causes problems with the JSplitPane */}
            }
        }
        public void drop(DropTargetDropEvent e) {
                Point p = e.getLocation();
                TreePath destPath = getPathForLocation(p.x, p.y);
                
                DefaultMutableTreeNode oldNode = selectedNode, destNode;
                if(destPath == null) {
                    destNode = rootNode;
                } else {
                    destNode = (DefaultMutableTreeNode)destPath.getLastPathComponent();
                }
                String oldParentName, newParentName = null;
                if(oldNode instanceof Account) {
                    Account account = (Account)selectedNode;
                    oldParentName = account.getParentName();
                    if(destNode instanceof Account) {
                        newParentName = ((Account)destNode).getParentName();
                    } else if(destNode instanceof Group) {
                        newParentName = ((Group)destNode).getName();
                    } else if(destNode.isRoot()) {
                        newParentName = "LockCrypt";
                    } else {
                        MessageFormat formatter = new MessageFormat(lang.getString("ERR_MOVINGGROUPS"));
                        JOptionPane.showMessageDialog(this, lang.getString("ERROR")+"#201: "+formatter.format(new Object[] {"1"}), lang.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
                    }
                    account.setGroup(newParentName);
                    e.acceptDrop(DnDConstants.ACTION_MOVE);
                } else if(oldNode instanceof Group) {
                    Group group = (Group)selectedNode;
                    oldParentName = group.getParentName();
                    if(destNode instanceof Account) {
                        newParentName = ((Account)destNode).getParentName();
                    } else if(destNode instanceof Group) {
                        newParentName = ((Group)destNode).getName();
                    } else if(destNode.isRoot()) {
                        newParentName = rootNode.toString();
                    } else {
                        MessageFormat formatter = new MessageFormat(lang.getString("ERR_MOVINGGROUPS"));
                        JOptionPane.showMessageDialog(this, lang.getString("ERROR")+"#202: "+formatter.format(new Object[] {"2"}), lang.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
                    }
                    group.setParentName(newParentName);
                    e.acceptDrop(DnDConstants.ACTION_MOVE);
                } else {
                    MessageFormat formatter = new MessageFormat(lang.getString("ERR_MOVINGGROUPS"));
                        JOptionPane.showMessageDialog(this, lang.getString("ERROR")+"#203: "+formatter.format(new Object[] {"3"}), lang.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
                }
                e.getDropTargetContext().dropComplete(true);
                parent.refreshAccountTree();
        }
        
        /** DragSourceListener interface methods */
        public void dragDropEnd(DragSourceDropEvent e) {}
        public void dragEnter(DragSourceDragEvent e) {}
        public void dragOver(DragSourceDragEvent e) {}
        public void dropActionChanged(DragSourceDragEvent e) {}
        public void dragExit(DragSourceEvent e) {}
        
        /** DropTargetListener interface methods */
        public void dragEnter(DropTargetDragEvent e) {}
        public void dragExit(DropTargetEvent e) {}
        public void dropActionChanged(DropTargetDragEvent e) {}
        public void dragOver(DropTargetDragEvent e) {
            e.acceptDrag(DnDConstants.ACTION_MOVE);
        }

        /* TreeSelectionListener */
        public void valueChanged(TreeSelectionEvent e) {
            selectedNode = (DefaultMutableTreeNode)this.getLastSelectedPathComponent();
            selectedTreePath = e.getNewLeadSelectionPath();
            if(selectedNode == null || parent.setJCEKey == null) {
                parent.setMenuButtons(0);
                return; //nothing was selected
            } else {
                parent.processNode(selectedNode);
            }
        }
}
